//
// Created by 王筱童 on 2022/5/10.
//

#include "database.h"
#include <iostream>

bool database::SET(const std::string &key, const std::string &value) {
    db_kv.insert({key,value});
    return true;
}

std::pair<bool, std::string> database::GET(const std::string &key) {
    auto it=db_kv.find(key);
    if(it!=db_kv.end()){
        return {true,it->second};
    }
    return {false,""};
}

bool database::DEL(const std::string &key) {
    db_kv.erase(key);
    return true;
}

bool database::EXISTS(const std::string &key) {
    return db_kv.contains(key);
}

std::pair<bool, std::string> database::HGET(const std::string &key, const std::string &field) {
    std::cout<<"key: "<<key<<std::endl;
    std::cout<<db_hash.empty()<<std::endl;
    for(auto &sk:db_hash){
        for(auto &sj:sk.second){
            std::cout<<sk.first<<' '<<sj.first<<' '<<sj.second<<std::endl;
        }
    }
    if(db_hash.contains(key)){
        if(db_hash[key].contains(field)){
            return {true,db_hash[key][field]};
        }
    }
    return {false,""};
}

bool database::HSET(const std::string &key, const std::string &field, const std::string &value) {
    db_hash[key][field]=value;
    return true;
}

bool database::HEXISTS(const std::string &key, const std::string &field) {

    if(db_hash.contains(key)){
        return db_hash[key].contains(field);
    }
    return false;
}

bool database::HDEL(const std::string &key,const std::string&field) {
    db_hash[key].erase(field);
    return true;
}

std::size_t database::HLEN(const std::string &key) {
    return db_hash[key].size();
}

std::vector<std::string> database::HGETALL(const std::string &key) {
    std::vector<std::string> res(db_hash[key].size());
    std::transform(db_hash[key].begin(),db_hash[key].end(),res.begin(),[](const std::pair<std::string,std::string>& pair){
        return pair.first+" "+pair.second;
    });
    return res;
}

std::size_t database::LLEN(const std::string &key) {
    return db_list[key].size();
}

bool database::LPUSH(const std::string &key, const std::string &value) {
    db_list[key].push_front(value);
    return true;
}

bool database::LPOP(const std::string& key) {
    if(db_list[key].empty()){
        return false;
    }
    db_list[key].pop_front();
    return true;
}

std::vector<std::string> database::LRANGE(const std::string &key, std::size_t begin, std::size_t end) {
    end=std::min(end,db_list[key].size()-1);
    begin=std::min(begin,end);
    auto it1=db_list[key].begin();
    auto it2=db_list[key].begin();
    std::advance(it1,begin);
    std::advance(it2,end);
    return {it1,it2};
}

std::string database::LINDEX(const std::string &key, std::size_t index) {
    index=std::min(index,db_list[key].size()-1);
    auto it=db_list[key].begin();
    std::advance(it,index);
    return *it;
}

bool database::RPUSH(const std::string &key, const std::string &val) {
    db_list[key].push_back(val);
    return true;
}

bool database::RPOP(const std::string &key) {
    if(db_list[key].empty()){
        return false;
    }
    db_list[key].pop_back();
    return true;
}

bool database::SADD(const std::string &key, const std::string &val) {
    db_set[key].insert(val);
    return true;
}

std::size_t database::SCARD(const std::string &k) {
    return db_set[k].size();
}

bool database::SREM(const std::string &key, const std::string &val) {
    db_set[key].erase(val);
    return true;
}

bool database::SCLR(const std::string &key) {
    db_set[key].clear();
    return true;
}

std::vector<std::string> database::SGET(const std::string &key) {
    return {db_set[key].begin(),db_set[key].end()};
}

bool database::ZADD(const std::string &key, const std::string &val) {
    db_zset[key].insert(val);
    return true;
}

std::vector<std::string> database::ZRANGE(const std::string&key ,const std::string& begin,const std::string& end){
    auto it1=db_zset[key].lower_bound(begin);
    auto it2=db_zset[key].lower_bound(end);
    return {it1,it2};
}

std::size_t database::ZCARD(const std::string &key) {
    return db_zset[key].size();
}

bool database::ZREM(const std::string &key, const std::string &val) {
    db_zset[key].erase(val);
    return true;
}

bool database::ZCLR(const std::string &key) {
    db_zset[key].clear();
    return true;
}

std::vector<std::string> database::ZGET(const std::string &key) {
    return {db_zset[key].begin(),db_zset[key].end()};
}

database::~database() {
    std::cout<<"destory"<<std::endl;
}


